package com.yhy.common.service;

import com.google.common.collect.Maps;
import com.yhy.common.api.IWorkflowService;
import com.yhy.common.constants.*;
import com.yhy.common.dao.BaseSimpleMngDao;
import com.yhy.common.dto.BaseMainEntity;
import com.yhy.common.dto.BaseMngDTO;
import com.yhy.common.dto.BaseMngVO;
import com.yhy.common.dto.workflow.WorkflowInfo;
import com.yhy.common.exception.BusinessException;
import com.yhy.common.utils.BusCenterHelper;
import com.yhy.common.utils.JsonUtils;
import com.yhy.common.utils.SpringContextHolder;
import com.yhy.common.utils.YhyUtils;
import com.yhy.common.vo.BusCommonState;
import com.yhy.common.vo.BusExtendVO;
import com.yhy.common.vo.SysAttachment;
import com.yhy.common.vo.SysUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/*
 *
 *  * *
 *  *  * <br>
 *  *  * <b>功能：</b><br>
 *  *  * <b>作者：</b>yanghuiyaun<br>
 *  *  * <b>日期：</b> 20-4-25 下午4:10 <br>
 *  *  * <b>版权所有：<b>版权所有(C) 2020<br>
 *  *
 *
 */
@Service
@Transactional(rollbackFor = Exception.class)
public abstract class BaseSimpleMngService<T extends BaseMngDTO, E extends BaseMngVO> extends BaseMngService<T, E> {

    protected abstract BaseSimpleMngDao getBaseMngDao();

    @Override
    protected Boolean needUpdateMainSelfState() {
        return true;
    }

    @Override
    protected Integer processMainOfDelete(BaseMainEntity baseMainEntity, E busMainData) {
        //简单业务带状态的, 需恢复状态
        if(FunProcess.DESTORY.getVal().equals(busMainData.getFunProcess())) {
            baseMainEntity.setSelfState(BusSelfState.VALID.getVal());
            return getBaseMainService().updateBusState(baseMainEntity);
        } else if(FunProcess.CHANGE.getVal().equals(busMainData.getFunProcess())) {
            //删除
            return getBaseMainService().deleteById(baseMainEntity);
        }
        return getBaseMainService().deleteById(baseMainEntity);
    }

    @Override
    protected void processBusCommonStateOfDelete(E busMainData) {
        if(FunProcess.DESTORY.getVal().equals(busMainData.getFunProcess())) {
            // 从历史表中 恢复状态, busDate, funprocess
            getBusCommonStateService().updateRecoverSimpleState(busMainData.getBusId(), getBusModule());
            return;
        } else if(FunProcess.CHANGE.getVal().equals(busMainData.getFunProcess())) {
            //恢复状态
            BusCommonState oldBusCommonState = getBusCommonStateService().updateRecoverSimpleState(busMainData.getBusId(), getBusModule());
            getBaseMainService().updateEnableFlagForRecover(oldBusCommonState.getMainId(), "Y");
            return;
        }
        getBusCommonStateService().deleteCommonStateById(busMainData.getBusId(),getBusModule());
    }

    @Override
    protected void processBusCommonStateOfSave(T baseDTO, E busMainData) {
        BusCommonState busCommonState = baseDTO.getBusCommonState();
        if (OperateType.EDIT.getVal().equals(baseDTO.getOperateType())) {
            BusCommonState updateBusCommonState = getBusCommonStateService().findByBusModuleAndId(getBusModule(), busCommonState.getId());
            updateBusCommonState.setBusType(busCommonState.getBusType());
            updateBusCommonState.setBusDate(busCommonState.getBusDate());
            updateBusCommonState.setCustomCode(busCommonState.getCustomCode());
            getBusCommonStateService().update(updateBusCommonState);
        } else if(FunProcess.CHANGE.getVal().equals(busMainData.getFunProcess())) {
            // 新建变更
            //保存历史记录
            BusCommonState oldBusCommonState = getBusCommonStateService().findByBusModuleAndId(getBusModule(), busCommonState.getId());
            getBusCommonStateService().saveSimpleHistory(oldBusCommonState);

            // 更新简单业务状态表(状态,时间,功能处理, 版本)
            FunProcess funProcess = FunProcess.CHANGE;
            busMainData.setBusDate(YhyUtils.getCurDateTime());
            busMainData.setFunProcess(funProcess.getVal());
            busMainData.setBusVersion(oldBusCommonState.getBusVersion() + 1);
            getBusCommonStateService().updateSimpleBusState(oldBusCommonState.getId(), getBusModule(), BusSelfState.DRAFT,
                    busMainData.getBusDate(), funProcess, busMainData.getBusRmk(),busMainData.getBusVersion(),busMainData.getId());
        } else {
            busCommonState.setId(null);
            busCommonState.setBusVersion(1);
            busCommonState.setSelfState(BusSelfState.DRAFT.getVal());
            busCommonState.setMainId(busMainData.getId());
            busCommonState.setBusModule(getBusModule());
            busCommonState.setBusClass(getBusClass());
            busCommonState.setOtherState(BusOtherState.VALID.getVal());
            busCommonState.setHistoryFlag("N");
            if (StringUtils.isBlank(busCommonState.getFunProcess())) {
                busCommonState.setFunProcess(FunProcess.NEW.getVal());
            }
            if (BusCenterHelper.isNeedFeedback(getBusModule())) {
                busCommonState.setOtherState(BusOtherState.WAIT_FEEDBACK.getVal());
            }
            getBusCommonStateService().insert(busCommonState);
            busMainData.setBusId(busCommonState.getId());
        }
    }

    protected void beforeDestoryOfProcess(E busMainData) {

    }

    protected void afterProcessCustomDataOfDestory(E busMainData) {

    }

    @Override
    protected BusSelfState startWorkflowOfBusiness(String userAccount, E busMainData) {
        //return BusSelfState.VALID;
        IWorkflowService workflowService = SpringContextHolder.getBean(IWorkflowService.SERVICE_BEAN);
        Map<String,Object> paramMap = Maps.newHashMap();
        paramMap.put("busMainData",busMainData);
        WorkflowInfo workflowInfo = new WorkflowInfo();
        workflowInfo.setPassByDirect(busMainData.getPassDirect());
        workflowInfo.setBusinessKey(busMainData.getBusId());
        workflowInfo.setBusModule(getBusModule());
        workflowInfo.setBusClass(getBusClass());
        if(BusCenterHelper.isOrgsetMng(getBusModule())) {
            workflowInfo.setSysOrgCode(busMainData.getSysOrgCode());
        }
        workflowInfo.setSysOwnerCpy(busMainData.getSysOwnerCpy());
        beforeSubmitOfWorkflowInfo(workflowInfo, busMainData);
        return workflowService.submitWorkflow(userAccount, workflowInfo, paramMap);
    }

    public void doSingleDestory(T baseDTO, E busMainData) {
        RedisLock redisLock = null;
        try {
            if(!BusSelfState.VALID.getVal().equals(busMainData.getSelfState())) {
                throw new BusinessException("请选择有效状态的记录进行注销!");
            }
            if(FunProcess.DESTORY.getVal().equals(busMainData.getFunProcess())) {
                throw new BusinessException("请选择非注销记录进行注销!");
            }
            //防止同步操作
            String redisLockKey = busMainData.getSysOwnerCpy() + (BusCenterHelper.isComplexBus(getBusModule()) ? busMainData.getSysGenCode() : busMainData.getId());
            if (StringUtils.isNotBlank(redisLockKey)) {
                redisLock = new RedisLock(redisLockKey, 200L); //100ms
                if (!redisLock.lock()) {
                    LOGGER.error("注销的数据已发生变化，请刷新页面重试." + redisLockKey);
                    throw new BusinessException("注销的数据已发生变化，请刷新页面重试.");
                }
            }

            preSetCommonBaseDto(baseDTO);

            beforeDestoryOfProcess(busMainData);

            SysUser sysUser = baseDTO.getSysUser();
            //状态设置
            BusSelfState busSelfState = BusSelfState.DRAFT;
            if(baseDTO.getListSubmit()) {
                //提交时启动工作流
                busSelfState = startWorkflowOfBusiness(sysUser.getUserAccount(), busMainData);
            }
            busMainData.setSelfState(busSelfState.getVal());
            BaseMainEntity baseMainEntity = JsonUtils.tranObject(busMainData, baseDTO.getBusMain().getClass());
            // 更新业务主表状态
            int updateNum = getBaseMainService().updateBusState(baseMainEntity);
            if(updateNum == 0) {
                LOGGER.error("注销时数据已发生变化，请刷新页面." + JsonUtils.toJson(baseMainEntity));
                throw new BusinessException("数据已发生变化，请刷新页面.");
            }
            busMainData.setVersion(busMainData.getVersion()+1);

            //保存历史记录
            BusCommonState oldBusCommonState = JsonUtils.tranObject(busMainData, BusCommonState.class);
            oldBusCommonState.setId(busMainData.getBusId());
            oldBusCommonState.setHistoryFlag("Y");
            oldBusCommonState.setSelfState(BusSelfState.VALID.getVal());
            oldBusCommonState.setRmk(busMainData.getBusRmk());
            getBusCommonStateService().saveSimpleHistory(oldBusCommonState);

            // 更新简单业务状态表(状态,时间,功能处理, 版本)
            FunProcess funProcess = FunProcess.DESTORY;
            busMainData.setBusDate(YhyUtils.getCurDateTime());
            busMainData.setFunProcess(funProcess.getVal());
            busMainData.setBusVersion(busMainData.getBusVersion() + 1);
            getBusCommonStateService().updateSimpleBusState(busMainData.getBusId(), getBusModule(), busSelfState,
                    busMainData.getBusDate(), funProcess, busMainData.getBusRmk(),busMainData.getBusVersion(),null);

            //注销后的记录处理
            afterProcessCustomDataOfDestory(busMainData);

            if(BusSelfState.VALID == busSelfState) {
                processBusCommonStateOfValid(busMainData);
            }

        } finally {
            if (redisLock != null) {
                redisLock.unlock();
            }
        }
    }

    @Override
    public void processBusCommonStateOfValid(E busMainData) {
        super.processBusCommonStateOfValid(busMainData);
        // 将注销的状态直接置为 无效
        if(FunProcess.DESTORY.getVal().equals(busMainData.getFunProcess())) {
            getBusCommonStateService().updateBusState(busMainData.getBusId(), getBusModule(), BusSelfState.INVALID);
            BaseMainEntity baseMainEntity = JsonUtils.tranObject(busMainData, getBusDTOInst().getBusMain().getClass());
            // 更新主表状态
            baseMainEntity.setSelfState(BusSelfState.INVALID.getVal());
            getBaseMainService().updateBusState(baseMainEntity);
        }
    }

    public void toChangeData(T baseDTO) {
        preSetCommonBaseDto(baseDTO);
        E busMainData = findByBusId(baseDTO.getParamBean().getId());
        if(!BusSelfState.VALID.getVal().equals(busMainData.getSelfState())) {
            throw new BusinessException("当前记录未生效，不能变更");
        }
        if(FunProcess.DESTORY.getVal().equals(busMainData.getFunProcess())) {
            throw new BusinessException("选择新建或变更的记录进行变更");
        }
        baseDTO.setFunProcess(FunProcess.CHANGE.getVal());
        baseDTO.setOperateType(OperateType.CREATE.getVal());
        busMainData.setFunProcess(FunProcess.CHANGE.getVal());
        busMainData.setSelfState(BusSelfState.DRAFT.getVal());
        busMainData.setParentId(busMainData.getBusId());
        String oldId = busMainData.getId();
        busMainData.setOldMainId(oldId);
        busMainData.setId(null);

        baseDTO.setBusMainData(busMainData);
        BusCommonState busCommonState = JsonUtils.tranObject(baseDTO.getBusMainData(), BusCommonState.class);
        busCommonState.setId(busMainData.getBusId());
        busCommonState.setParentId(busMainData.getBusId());
        busCommonState.setBusDate(YhyUtils.getCurDateTime());
        baseDTO.setBusCommonState(busCommonState);

        //业务扩展表
        BusClassType busClassType = BusClassType.getInstByVal(getBusClass());
        if(busClassType != null && busClassType.getExtendMng()) {
            BusExtendVO busExtend = getBusExtendService().findByBusModuleAndMainId(getBusModule(), busMainData.getOldMainId());
            busExtend = busExtend == null ? new BusExtendVO() : busExtend;
            busExtend.setId(null);
            busExtend.setMainId(null);
            String formApplyId = busExtend.getFormApplyId();
            busExtend.setSourceFormApplyId(formApplyId);
            baseDTO.setBusExtend(busExtend);
        }

        //附件
        if (BusCenterHelper.isAttachmentMng(getBusModule())) {
            List<SysAttachment> sysAttachments = getSysAttachmentService().findByMainId(getBusModule(),busMainData.getOldMainId());
            baseDTO.setAttachmentList(sysAttachments);
        }
        afterProcessCustomDataOfChange(baseDTO,busMainData);
    }

    protected void afterProcessCustomDataOfChange(T baseDTO, E busMainData) {

    }

}
